import { exec } from 'egret/base/common/cmd';
import { isMacintosh } from 'egret/base/common/platform';
import { normalizeNFC } from 'egret/base/common/strings';
import URI from 'egret/base/common/uri';
import { ISelectedStat } from 'egret/platform/files/common/files';
import { getDefaultResPath, getDirPath } from 'egret/platform/workspace/common/workspace';
import * as fs from 'fs';
import * as paths from 'path';

/**
 * 选择文件，这个方法是递归的
 * @param resource 开始查找的文件
 * @param exts 要查找的扩展名，如['.bmp','.txt']
 * @param onSelected 每查到一个目标文件的时候调用
 */
export function select(resource: URI, exts: string[], onSelected?: (stat: ISelectedStat) => void, ignores?: string[]): Promise<ISelectedStat[]> {
	const newExts: string[] = [];
	for (let i = 0; i < exts.length; i++) {
		newExts.push(exts[i].toLocaleLowerCase());
	}
	return new Promise<ISelectedStat[]>((resolve, reject) => {
		const selectedStats: ISelectedStat[] = [];
		const onCompelte = () => {
			resolve(selectedStats);
		};
		doSelect(resource.fsPath, newExts, onSelected, selectedStats, onCompelte, null, ignores);
	});
}

function doSelect(path: string, exts: string[], onSelected: (stat: ISelectedStat) => void, fileStats: ISelectedStat[], onComplete: () => void, selectedMap?: { [path: string]: boolean }, ignores?: string[]): void {
	if (!selectedMap) {
		selectedMap = Object.create(null);
	}

	const baseName = paths.basename(path);
	if (ignores.indexOf(baseName) != -1) {
		onComplete();
		return;
	}
	fs.stat(path, (error, stat) => {
		if (error) {
			onComplete();
			return;
		}
		if (!stat.isDirectory()) {
			let ext = paths.extname(path);
			if (!ext) {
				ext = '';
			}
			ext = ext.toLocaleLowerCase();
			if (exts.length > 0) {
				if (exts.indexOf(ext) != -1) {
					var selectedStat: ISelectedStat = {
						resource: URI.file(path),
						name: paths.basename(path),
						mtime: stat.mtime.getTime(),
						ext: ext
					};
					fileStats.push(selectedStat);
					if (onSelected) {
						onSelected(selectedStat);
					}
				}
			} else {
				var selectedStat: ISelectedStat = {
					resource: URI.file(path),
					name: paths.basename(path),
					mtime: stat.mtime.getTime(),
					ext: ext
				};
				fileStats.push(selectedStat);
				if (onSelected) {
					onSelected(selectedStat);
				}
			}
			onComplete();
			return;
		}
		if (selectedMap[path]) {
			onComplete();
			return;
		}
		selectedMap[path] = true;
		readdir(path, (err, files) => {
			if (files) {
				const numSum = files.length;
				let numFinish = 0;
				const checkComplete = () => {
					if (numFinish == numSum) {
						onComplete();
					}
				};
				const clb = () => {
					numFinish++;
					checkComplete();
				};
				for (let i = 0; i < files.length; i++) {
					const file = files[i];
					doSelect(paths.join(path, file), exts, onSelected, fileStats, clb, selectedMap, ignores);
				}
				checkComplete();
			} else {
				onComplete();
			}
		});
	});
}

export function readdir(path: string, callback: (error: Error, files: string[]) => void): void {
	if (isMacintosh) {
		return fs.readdir(path, (error, children) => {
			if (error) {
				return callback(error, null);
			}
			return callback(null, children.map(c => normalizeNFC(c)));
		});
	}
	return fs.readdir(path, callback);
}

/**对项目内的文件重新写入一下 针对绿盾然后会造成乱码的问题 */
export async function readSrcAllTsFile() {
	try {
		console.warn('readSrcAllTsFile');
		const cwd = getDirPath();
		const command = `node ./euiEditorScript.js reWrite ${paths.join(cwd, 'src')}`;
		if (fs.existsSync(paths.join(cwd, 'euiEditorScript.js'))) {
			return exec(command, getDirPath());
		}
	} catch (error) {
		console.error("执行脚本错误", error);
	}
}

/**对项目内的文件重新写入一下 针对绿盾然后会造成乱码的问题 */
export async function reWriteFile(file: string) {
	try {
		const cwd = getDirPath();
		const url = paths.join(cwd, file.replace(cwd, ""));
		if (fs.existsSync(url)) {
			const command = `node ./euiEditorScript.js reWrite ${url}`;
			if (fs.existsSync(paths.join(cwd, 'euiEditorScript.js'))) {
				return exec(command, getDirPath());
			}
		}
		return Promise.resolve();
	} catch (error) {
		console.error("执行脚本错误", error);
	}
}

/**对项目内的文件重新写入一下 针对绿盾然后会造成乱码的问题 */
export async function reWriteFileSync(file: string) {
	try {
		const cwd = getDirPath();
		const url = paths.join(cwd, file.replace(cwd, ""));
		if (fs.existsSync(url)) {
			const command = `node ./euiEditorScript.js reWrite ${url}`;
			if (fs.existsSync(paths.join(cwd, 'euiEditorScript.js'))) {
				return exec(command, getDirPath());
			}
		}
	} catch (error) {
		console.error("执行脚本错误", error);
	}
}

/**以增量的形式写入一个资源文件 */
export async function addResByModule(moduleName: string, res: string, lan: 'zh_cn' | 0 = 0, isReplace: boolean = false) {
	const cwd = getDirPath();
	// let command = `node ./euiEditorScript.js addRes ${moduleName} ${res} ${lan} ${isReplace}`;
	let command = `node ./euiEditorScript.js addRes ${moduleName} "${res}" ${lan} ${isReplace}`;
	if (fs.existsSync(paths.join(cwd, 'euiEditorScript.js'))) {
		try {
			const log = await exec(command, cwd);
			return log;
		} catch (e) {
			append('执行脚本失败,打开控制台看看有什么报错。');
			console.error(e);
			return Promise.resolve("");
		}
	}
	return Promise.resolve("");
}

function append(text: string) {
	global['___OutputView'] && global['___OutputView'].append(text);
}

const resJson: { [name: string]: string } = {};
const sheetMap: { [name: string]: string } = {};

export function cacheResJson() {
	const url = getDefaultResPath();
	if (fs.existsSync(url)) {
		const str = fs.readFileSync(url, 'utf8');
		const obj = JSON.parse(str);
		obj.resources.forEach(resource => {
			resJson[resource.name] = resource.url;
			const sheetName = resource.url.match(/[^\/]+_sheet/)?.[0];
			if (sheetName && sheetName.length) {
				const url = resource.url.substring(0, resource.url.indexOf(sheetName) + sheetName.length);
				let name = sheetName;
				if (url.includes('zh_cn')) {
					name = `(zh_cn)` + name;
				}
				sheetMap[name] = url;
			}
		});
	}
	const zh_cn = getDefaultResPath('zh_cn');
	if (fs.existsSync(zh_cn)) {
		const str = fs.readFileSync(zh_cn, 'utf8');
		const obj = JSON.parse(str);
		obj.resources.forEach(resource => {
			resJson[resource.name] = resource.url;
			const sheetName = resource.url.match(/[^\/]+_sheet/)?.[0];
			if (sheetName && sheetName.length) {
				const url = resource.url.substring(0, resource.url.indexOf(sheetName) + sheetName.length);
				let name = sheetName;
				if (url.includes('zh_cn')) {
					name = `(zh_cn)` + name;
				}
				sheetMap[name] = url;
			}
		});
	}
	console.warn("sheetMap", sheetMap);
}

/**根据资源名称获取路径 */
export function getResUrl(name: string): string {
	return resJson[name];
}

/**根据图集名获取图集地址 */
export function getSheetUrl(name: string): string {
	return sheetMap[name];
}

/**获取可以转入的图集 */
export function getSheets(moduleName?: string, lan?: "zh_cn") {
	const arr = [];
	for (const name in sheetMap) {
		const lanBool = lan ? sheetMap[name].includes(lan) : !sheetMap[name].includes('locate/');
		const url = sheetMap[name];
		if (lanBool) {
			if (url.includes('common')) {
				arr.push(name);
			} else if (url.includes('temp_sheet')) {
				arr.push(name);
			} else if (moduleName && sheetMap[name].includes(moduleName)) {
				arr.unshift(name);
			}
		}
	}
	return arr;
}

global['getSheets'] = getSheets;